/*/////////////////////////////////////////////////////////////////////////////////
/// An
///    ___   ____ ___ _____ ___  ____
///   / _ \ / ___|_ _|_   _/ _ \|  _ \
///  | | | | |  _ | |  | || | | | |_) |
///  | |_| | |_| || |  | || |_| |  _ <
///   \___/ \____|___| |_| \___/|_| \_\
///                              File
///
/// Copyright (c) 2008-2009 Ismail TARIM <ismail@royalspor.com> and the Ogitor Team
//
//This program is free software; you can redistribute it and/or modify it under
//the terms of the GNU Lesser General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
//
//This program is distributed in the hope that it will be useful, but WITHOUT
//ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
//FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public License along with
//this program; if not, write to the Free Software Foundation, Inc., 59 Temple
//Place - Suite 330, Boston, MA 02111-1307, USA, or go to
//http://www.gnu.org/copyleft/lesser.txt.
////////////////////////////////////////////////////////////////////////////////*/

#pragma once

#include "OgitorsSingleton.h"

namespace Ogitors
{
	/// A Hashed by Name Storage Definition for All Serializers
	typedef OgitorExport HashMap<Ogre::String,CBaseSerializer*> SerializerMap;

	//! A mouse listener class
	/*!  
	A mouse listener class that is used to capture mouse events, button(s) pressed and/or mouse position
	*/ 
	class OgitorExport MouseListener
	{
	public:
		/**
		* Constructor
		*/
		MouseListener() {};
		/**
		* Destructor
		*/
		virtual ~MouseListener() {};

		/**
		* Delegate function for mouse move event
		* @param viewport window to receive the input
		* @param point new mouse position
		* @param buttons mouse button flags 
        * @see QMouseEvent
		*/
		virtual void OnMouseMove (CViewportEditor *viewport, Ogre::Vector2 point, unsigned int buttons) = 0;
		/**
		* Delegate function for mouse leave event
		* @param viewport window to receive the input
		* @param point new mouse position
        * @param buttons mouse button flags  
        * @see QMouseEvent
		*/
		virtual void OnMouseLeave (CViewportEditor *viewport, Ogre::Vector2 point, unsigned int buttons) = 0;
		/**
		* Delegate function for mouse left button down event
		* @param viewport window to receive the input
		* @param point new mouse position
        * @param buttons mouse button flags  
        * @see QMouseEvent
		*/
		virtual void OnMouseLeftDown (CViewportEditor *viewport, Ogre::Vector2 point, unsigned int buttons) = 0;
		/**
		* Delegate function for mouse left button up event
		* @param viewport window to receive the input
		* @param point new mouse position
        * @param buttons mouse button flags  
        * @see QMouseEvent
		*/
		virtual void OnMouseLeftUp (CViewportEditor *viewport, Ogre::Vector2 point, unsigned int buttons) = 0;
		/**
		* Delegate function for mouse right button down event
		* @param viewport window to receive the input
		* @param point new mouse position
        * @param buttons mouse button flags  
        * @see QMouseEvent
		*/
		virtual void OnMouseRightDown (CViewportEditor *viewport, Ogre::Vector2 point, unsigned int buttons) = 0;
		/**
		* Delegate function for mouse right button up event
		* @param viewport window to receive the input
		* @param point new mouse position
        * @param buttons mouse button flags
        * @see QMouseEvent
		*/
		virtual void OnMouseRightUp (CViewportEditor *viewport, Ogre::Vector2 point, unsigned int buttons) = 0;
		/**
		* Delegate function for mouse middle button down event
		* @param viewport window to receive the input
		* @param point new mouse position
        * @param buttons mouse button flags  
        * @see QMouseEvent
		*/
		virtual void OnMouseMiddleDown (CViewportEditor *viewport, Ogre::Vector2 point, unsigned int buttons) = 0;
		/**
		* Delegate function for mouse middle button up event
		* @param viewport window to receive the input
		* @param point new mouse position
        * @param buttons mouse button flags  
        * @see QMouseEvent
		*/
		virtual void OnMouseMiddleUp (CViewportEditor *viewport, Ogre::Vector2 point, unsigned int buttons) = 0;
		/**
		* Delegate function for mouse wheel movement (up or down)
		* @param viewport window to receive the input
		* @param point new mouse position
		* @param delta change of mouse scrolling position
        * @param buttons mouse button flags  
        * @see QMouseEvent
		*/
		virtual void OnMouseWheel (CViewportEditor *viewport, Ogre::Vector2 point, float delta, unsigned int buttons) = 0;
	};

	//! A keyboard listener class
	/*!  
	A keyboard listener class that is used to capture keyboard events
	*/ 
	class OgitorExport KeyboardListener
	{
	public:
		/**
		* Constructor
		*/
		KeyboardListener() {};
		/**
		* Destructor
		*/
		virtual ~KeyboardListener() {};

		/**
		* Delegate function for keyboard key down event
		* @param key key that is down at the moment (not pressed)
		* @return true if key is down, return true, otherwise false
		*/
		virtual bool OnKeyDown (unsigned short key) = 0;
		/**
		* Delegate function for keyboard key up (released) event
		* @param key key that has just been released
		* @return true if key had just been released, otherwise false
		*/
		virtual bool OnKeyUp (unsigned short key) = 0;
	};
	
	//! Drag & Drop Handler class
	/*!  
	A Drag & Drop Handler class that is used to handle drag&drop events sent to render window	
	*/ 
	class OgitorExport DragDropHandler
	{
	public:
		/**
		* Constructor
		*/
		DragDropHandler() {};
		/**
		* Destructor
		*/
		virtual ~DragDropHandler() {};

		/**
		* Delegate function for drag enter event
		* @return true if the drag event accepted, otherwise false
		*/
		virtual bool OnDragEnter () = 0;
		/**
		* Delegate function for drag leave event
		*/
		virtual void OnDragLeave () = 0;
		/**
		* Delegate function for drag move event
		* @param vp the viewport in which the event occured
		* @param position mouse position relative to the viewports width/height
		* @return true if the drag event accepted, otherwise false
		*/
		virtual bool OnDragMove (Ogre::Viewport *vp, Ogre::Vector2& position) = 0;
		/**
		* Delegate function for drag dropped event
		* @param vp the viewport in which the event occured
		* @param delta mouse delta 
		*/
		virtual void OnDragWheel (Ogre::Viewport *vp, float delta) = 0;
		/**
		* Delegate function for drag dropped event
		* @param vp the viewport in which the event occured
		* @param position mouse position relative to the viewports width/height
		*/
		virtual void OnDragDropped (Ogre::Viewport *vp, Ogre::Vector2& position) = 0;
	};

	//! A preferences editor class
	/*!  
	A class that is responsible for handling plugin values exposed to the editor
	*/
	class OgitorExport PreferenceEditor
	{
	public:
		/**
		* Fetches preferences list
		* @param preferences place to fill preference values into
		*/
		virtual void  getPreferences(Ogre::NameValuePairList& preferences) = 0;
		/**
		* Fetches a QWidget pointer to put preferences into (internal use only)
		* @return A QWidget type pointer
		* @see QWidget
		*/
		virtual void *getPreferencesWidget() = 0;
		/**
		* Applies preferences to the Ogitor
		* @return true if preferences were applied successfully, otherwise false
		*/
		virtual bool  applyPreferences() = 0;
	};

	//! Preferences registration
	/*!  
	A structure that is responsible for editor plugin registration
	*/
	struct PreferenceEditorRegistrationStruct
	{
		Ogre::String      Identifier;
		Ogre::String      ImagePath;
		PreferenceEditor *PrefEditor;
	};

	typedef OgitorExport std::vector<PreferenceEditorRegistrationStruct> PreferenceEditorVector;

	typedef OgitorExport std::map<void *, DragDropHandler*> DragDropHandlerMap;

	//! Listener class
	/*!  
	A class that is used to signal the events occuring in the editor
	*/
	class OgitorsRootListener
	{
	public:
		/**
		* Constructor
		*/
		OgitorsRootListener() {};
		/**
		* Destructor
		*/
		virtual ~OgitorsRootListener() {};

		/**
		* Delegate function that is called when scene is about to be destroyed
		*/
		virtual void OnTerminateScene() = 0;
		/**
		* Delegate function that is called when scene has been loaded
		*/
		virtual void OnAfterLoadScene() = 0;
		/**
		* Delegate function that is called when scene has been updated
		*/
		virtual void OnUpdate(float time) = 0;
	};

	//! This is the Root Class in Charge of All Editors
	/*!  

	*/
	class OgitorExport OgitorsRoot: public Singleton<OgitorsRoot>
	{
		friend class CBaseEditor;
	public:
		/**
		* Constructor, initialises with platform dependant system classes
		*/ 
		OgitorsRoot();
		/**
		* Destructor
		*/
		~OgitorsRoot();
		/**
		* Registers new root listener
		*/
		void            RegisterRootListener(OgitorsRootListener *listener);
		/**
		* Unregisters specified root listener
		* @param listener root listener
		*/
		void            UnRegisterRootListener(OgitorsRootListener *listener);
		/**
		* Registers a new editor object factory
		* @param pluginIdentifier the id given to the plugin when dllStartPlugin is called
		* @param factory pointer to the new factory to be registered
		*/
		void            RegisterEditorFactory(void *pluginIdentifier, CBaseEditorFactory *factory);
		/**
		* Registers a new serializer
		* @param serializer additional serializer
		*/
		void            RegisterSerializer(void *pluginIdentifier, CBaseSerializer *serializer);
		/**
		* Fetches a list filled with registered serializer type names
		* @param list a list to place serializer type names into
		*/
		void            GetSerializerList(Ogre::StringVector &list);
		/**
		* Fetches a list filled with registered serializer type names capable of export
		* @param list a list to place serializer type names into
		*/
		void            GetExportSerializerList(Ogre::StringVector &list);
		/**
		* Returns a list filled with registered serializer type names capable of import
		* @param list a list to place serializer type names into
		*/
		void            GetImportSerializerList(Ogre::StringVector &list);
		/**
		* Triggers an import serializer
		* @param name name of the serializer
		*/
		bool            TriggerImportSerializer(Ogre::String name);
		/**
		* Triggers an export serializer
		* @param name name of the serializer
		*/
		bool            TriggerExportSerializer(Ogre::String name);
		/**
		* Fetches registration data for an editor object type
		* @param typeName type of an object
        * @return the factory with associated the typename, otherwise 0
		*/
		CBaseEditorFactory *GetEditorObjectFactory(const Ogre::String& typeName);
		/**
		* Returns a list of all Registered Editor Object Factories
		*/
        EditorObjectFactoryMap GetEditorObjectFactories() {return m_EditorObjectFactories;};
		/**
		* Fetches type ID of a factory associated with the type name
		* @param typeName type name of editor object factory
		* @return type ID if found, otherwise 0
		*/
		unsigned int    GetTypeID(const Ogre::String& typeName);
		/**
		* Registers an object name for the editor
		* @param name object name
		* @param obj editor associated with an object
		*/
		void            RegisterObjectName(Ogre::String name,CBaseEditor *obj);
		/**
		* Unregisters an object (called upon deletion of object)
		* @param name object name
		* @param obj editor associated with an object
		*/
		void            UnRegisterObjectName(Ogre::String name,CBaseEditor *obj);
		/**
		* A delegate function between Terrain and Hydrax that is used when ETL material changes
		* @param terrainobject terrain editor for which material has been changed
		*/
		void            OnTerrainMaterialChange(CBaseEditor *terrainobject);
		/**
		* Registers object for updates if it needs to update every frame
		* @param object editor object
		*/
		void            RegisterForUpdates(CBaseEditor *object);
		/**
		* Unregisters object from receiving updates
		* @param object editor object
		*/
		void            UnRegisterForUpdates(CBaseEditor *object);
		/**
		* This function should be called every frame in Frame Started
		* @param
		* @return
		*/
		bool            Update(float timePassed);
		/**
		* An object registers itself for updates if it needs to update when scene is loaded
		* @param object an object to receive post-update event
		*/
		void            RegisterForPostSceneUpdates(CBaseEditor *object);
		/**
		* Locates child by a name or ID
		* @param name name of an object to locate
		* @param type type of object to locate
		* @return an object pointer if found, otherwise 0
		*/
		CBaseEditor    *FindObject(Ogre::String name, unsigned int type = 0);
		/**
		* Fetches a list key-value pairs of objects with specified type
		* @param type type of an Object
		* @return a list of key-value pairs of objects that have specified type
		*/
		const NameObjectPairList GetObjectsByType(unsigned int type);
		/**
		* Fetches a list key-value pairs of objects with specified type name
		* @param typeName type name of objects to be fetched
		* @return a list of key-value pairs of objects that have specified type name
		*/
		const NameObjectPairList GetObjectsByTypeName(const Ogre::String& typeName);
		/**
		* Fetches all objects of a specified type (Used while saving scene since it also orders the items)
		* @param type type of an object
		* @param list a list to place objects with specified type into
		*/
		void            GetObjectList(unsigned int type, ObjectVector& list);
		/**
		* Fetches top level editor object
		* @return root editor
		*/
		CBaseEditor    *GetRootEditor() {return m_RootEditor;};
		/**
		* Clears project options
		*/
		void            ClearProjectOptions();
		/**
		* Fetches project options
		* @return a pointer to project options
		*/
		PROJECTOPTIONS *GetProjectOptions() {return &m_ProjectOptions;}
		/**
		* Loads a scene from specified file
		* @param Filename file name for the scene to be loaded
		* @return result of loading (or attempting) a scene
		* @see SCENEFILERESULT
		*/
		int             LoadScene(Ogre::String Filename);
		/**
		* Saves current scene into a file
		* @param SaveAs flag to save scene at different location as specified by user in SaveAs dialog 
		* @return true if scene was saved successfully, otherwise false 
        * @see SCENEFILERESULT for return results
		*/
		bool            SaveScene(bool SaveAs = false);
		/**
		* Terminates current scene
		* @return true if scene was terminated (and saved after being modified) or not modified at all, otherwise false
		*/
		bool            TerminateScene();
		/**
		* Peforms necessary actions after scene was loaded successfully
		* @return unconditional true
		* @todo See if return type should be changed to void
		*/
		bool            AfterLoadScene();
		/**
		* Loads project options from an XML element
		* @param optRoot XML element to load project options from
		* @return true if options were loaded successfully, otherwise false
		*/
		bool            LoadProjectOptions(TiXmlElement *optRoot);
		/**
		* Loads camera positions from an XML element
		* @param parent top XML element containing camera position(s) XML elements
		* @return true if loaded successfully, otherwise false
		*/
		bool            OptionsReadCameraPositions(TiXmlElement *parent);
		/**
		* Loads directory list from an XML element
		* @param parent top XML element containing directories XML elements 
		* @param pDir string list to place directories into
		* @return true if options were read successfully, otherwise false
		*/
		bool            OptionsReadDirectories(TiXmlElement *parent, Ogre::StringVector &pDir);
		/**
		* Prepares project resource group(s)
		*/
		void            PrepareProjectResources();
		/**
		* Converts relative project resource paths according to new project directory
		* @param oldpath previous path to project' scene file
		*/
		void            AdjustUserResourceDirectories(Ogre::String oldpath);
		/**
		* Creates an editor object using registered factory
		* @param parent parent editor object 
		* @param objecttypestring type of an object to be created
		* @param params additional list of parameters
		* @param addtotreelist to insert new object into scene if true, not otherwise
		* @return newly created object
		*/
		CBaseEditor    *CreateEditorObject(CBaseEditor *parent, const Ogre::String objecttypestring,Ogre::NameValuePairList &params,bool addtotreelist = false, bool display = false);
		/**
		* Clones an editor object using registered factory
		* @param object object to be cloned
		* @param addtotreelist to insert new object into scene tree view widget if true, not otherwise
		* @param display display newly cloned object in the scene
		* @return newly cloned object
		*/
		CBaseEditor    *CloneEditorObject(CBaseEditor *object,bool addtotreelist = false, bool display = false);
		/**
		* Destroys an editor object using registered factory
		* @param object object to be destroyed
		* @param removefromtreelist to remove new object from the scene tree view widget if true, not otherwise
		* @param display display destroyed object in the scene
		* @return newly cloned object
		*/
		void            DestroyEditorObject(CBaseEditor *object, bool removefromtreelist = false, bool display = false);
		/**
		* Tests if certain object can be instantiated (created)
		* @param typeName type of an object
		* @return true if object can be instantiated, otherwise false
		*/
		bool            CanInstantiateObject(const Ogre::String& typeName);

		// UTILITY FUNCTIONS
		/**
		* Creates a unique identifier string
		* @param n1 head of a string
		* @param n2 tail of the string
		* @param seed additional randomization seed
		* @return string with unique object identifier
		*/
		Ogre::String    CreateUniqueID(Ogre::String n1, Ogre::String n2, int seed = -1);
		/**
		* Writes camera position(s) into specified output stream
		* @param outstream output stream to write camera position(s) into
		* @param addcurrent if true, writes down current viewport' camera position(s)
		*/
		void            WriteCameraPositions(std::ostream &outstream, bool addcurrent);
		/**
		* Writes project options into specified output stream
		* @param outstream output stream to write project options into
		* @param newproject used for sub-call to COgitorsRoot::WriteCameraPositions
		*/
		void            WriteProjectOptions(std::ostream &outstream, bool newproject);
		/**
		* Loads project' property sheets (int, bool, string etc)
		*/
		void            LoadPropertySheets();
		/**
		* Unloads project' property sheets (int, bool, string etc)
		*/
		void            UnloadPropertySheets();
		/**
		* Loads project' custom properties (structures, classes like vector2, vector3 etc)
		*/
		void            LoadCustomProperties();
		/**
		* Fetches custom property by the name
		* @param name name of the custom property
		* @return pointer to custom property structure
		*/
		CUSTOMPROPERTY *GetCustomProperty(Ogre::String name);
		/**
		* Fetches custom property' ID
		* @param name name of the custom property
		* @return ID of the custom property if found, otherwise 0
		*/
		unsigned int    GetCustomPropertyID(Ogre::String name);
		/**
		* Fetches name of the custom property' type
		* @param ID ID of the property type
		* @return name of the property type, otherwise empty string
		*/
		Ogre::String    GetCustomPropertyTypeName(unsigned int ID);
		/**
		* Adds custom property to another, recursing into sub-properties of one to be added
		* @param to custom property to add another property (and sub-properties) to
		* @param from custom property which is to be added (and sub-properties of it, too)
		*/
		void            RecurseAddCustomProperty(CUSTOMPROPERTY *to, CUSTOMPROPERTY *from);
		/**
		* Deletes custom property and its sub-properties too recursively
		* @param p root property to delete
		*/
		void            RecurseDeleteCustomProperties(CUSTOMPROPERTY *p);
		/**
		* Fetches a string list of custom properties of a certain editor type
		* @param editortype type of an editor with which properties are associated with
		* @param result a string list to put properties into
		*/
		void            GetCustomPropertyList(unsigned int editortype, Ogre::StringVector &result);
		/**
		* Fetches information about OGRE-based mesh
		* @param mesh mesh to retrieve information about
		* @param vertex_count number of vertices to retrieve
		* @param vertices raw Ogre::Vector3 array pointer to mesh' vertices
		* @param index_count number of indices to retrieve
		* @param indices raw ulong array pointer to mesh' indices
		* @param position mesh position to retrieve
		* @param orient mesh orientation to retrieve
		* @param scale mesh scale to retrieve
		*/
		void            GetMeshInformationEx(const Ogre::MeshPtr mesh, size_t &vertex_count,
			Ogre::Vector3* &vertices, size_t &index_count,
			unsigned long* &indices,
			const Ogre::Vector3 &position,
			const Ogre::Quaternion &orient,
			const Ogre::Vector3 &scale);
		/**
		* Attempts to pick an entity within scene using ray cast from the mouse
		* @param mRaySceneQuery a ray scene query object 
        * @see Ogre::RaySceneQuery
        * @param ray ray cast from the mouse  
        * @see COgitorsRoot::GetMouseRay
		* @param result a result of entities that were intersected with the ray
		* @param hitpoint a closest point of the ray/entity intersection to the camera
		* @param max_distance check only objects closer than this value
		* @param excludeobject the name of the object to exclude from hit test
		* @return true if any entity was intersected with the ray, otherwise false
		*/
		bool          PickEntity(Ogre::RaySceneQuery* mRaySceneQuery, Ogre::Ray &ray, Ogre::Entity **result, Ogre::Vector3 &hitpoint, const Ogre::String& excludeobject = "", Ogre::Real max_distance = -1.0f);
		/**
		* Attempts to pick an entity within scene using ray cast from the mouse
		* @param mRaySceneQuery a ray scene query object 
        * @see Ogre::RaySceneQuery
        * @param ray ray cast from the mouse  
        * @see COgitorsRoot::GetMouseRay
		* @param result a result of entities that were intersected with the ray
		* @param hitpoint a closest point of the ray/entity intersection to the camera
		* @param max_distance check only objects closer than this value
		* @param excludeobjects the list of names of the objects to exclude from hit test
		* @return true if any entity was intersected with the ray, otherwise false
		*/
		bool          PickEntity(Ogre::RaySceneQuery* mRaySceneQuery, Ogre::Ray &ray, Ogre::Entity **result, Ogre::Vector3 &hitpoint, const Ogre::StringVector& excludeobjects, Ogre::Real max_distance = -1.0f);
		/**
		* Attempts to pick X, Y or Z axis gizmo(s) presented when object is moved, scaled etc
        * @param ray ray cast from the mouse  
        * @see COgitorsRoot::GetMouseRay
		* @param Axis axis of the selected gizmo
		* @return true if intersected with any of gizmo(s), otherwise false
		*/
		bool          PickGizmos(Ogre::Ray &ray, int &Axis);
		/**
		* Attempts to find the index of the submesh containing the point hitpoint
        * @param pEntity the parent Entity Object  
        * @see Ogre::Entity
 		* @param hitpoint the location on the Entity
		* @return the index of the submesh containing the hitpoint
		*/
        int           PickSubMesh(Ogre::Entity* pEntity, const Ogre::Vector3& hitpoint);
        /**
		* Calculates gizmo translation plane on the X, Y or Z axis
		* @param pickRay ray to pick gizmo with
		* @param TranslationAxis axis flags to use when finding the plane
        * @return a plane on which all axis reside on as specified in 2nd parameter  
        * @see AXISTYPE
		*/
		Ogre::Plane   FindGizmoTranslationPlane(Ogre::Ray &pickRay, int TranslationAxis);
		/**
		* Calculates the new position delta of the object according to mouse position and desired axis
		* @param pickRay a ray from camera position to mouse position in 3D space
		* @param planetouse a plane to be used for intersection tests with the pickRay
		* @param TranslationAxis the axis on which movement will be calculated
		* @param vLastPosition the last position from which the delta will be calculated
		* @return returns the delta from vLastPosition, will be calculated according to pickRay, Plane and Axis
		*/
		Ogre::Vector3 GetGizmoIntersect(Ogre::Ray &pickRay, Ogre::Plane &planetouse, int TranslationAxis, Ogre::Vector3 &vLastPosition);
		/**
		* Calculates the new position delta of the object according to mouse position and desired axis
		* @param object the object whose new position is being calculated
		* @param pickRay a ray from camera position to mouse position in 3D space
		* @return returns the new position of the object, calculated from the pickRay's intersection with camera's back plane
		*/
		Ogre::Vector3 GetGizmoIntersectCameraPlane(CBaseEditor *object, Ogre::Ray &pickRay);
        /**
		* Test if specified ray has intersected with anything on the scene
		* @param mRaySceneQuery ray scene query object helper 
		* @param ray a ray that is to be tested
		* @param hitposition location of an intersect (if any)
		* @return true if ray had intersected with anything, otherwise false
		*/
		bool          WorldIntersect(Ogre::RaySceneQuery* mRaySceneQuery, Ogre::Ray &ray, Ogre::Vector3 &hitposition);
		/**
		* Selects objects names that are within volume
		* @param topLeft top left ray boundary
		* @param topRight top right ray boundary
		* @param bottomLeft bottom left ray boundary
		* @param bottomRight bottom right ray boundary
		* @param result names of objects within volume
		*/
		void          VolumeSelect(Ogre::Ray &topLeft, Ogre::Ray &topRight, Ogre::Ray &bottomLeft, Ogre::Ray &bottomRight, NameObjectPairList &result);
		/**
		* Fills resource group with resource name & path from specified location
		* @param mngr group resource manager that will load resource(s)
		* @param list list of resource names to add to the group
		* @param path directory in which resources are located
		* @param group name of the group to add resource names to
		*/
		void          FillResourceGroup(Ogre::ResourceGroupManager *mngr,Ogre::StringVector &list,Ogre::String path,Ogre::String group);
		/**
		* Fetches currently selected object
		* @return currently selected object
		*/
		inline CBaseEditor *            GetSelected() {return m_SelectedEditor;};
		/**
		* Sets currently selected object
		* @param selected new object to be selected
		*/
		inline void                     SetSelected(CBaseEditor *selected) {m_SelectedEditor = selected;m_OldGizmoMode = 256;m_OldGizmoAxis = 256;};
		/**
		* Fetches names of materials in user assets folders
		* @return names of materials in user assets folders
		*/
		inline const Ogre::StringVector GetMaterialNames() {return m_MaterialNames;};
		/**
		* Sets names of the material(s) for current editor
		* @param names names of the material(s) for current editor
		*/
		inline void                     SetMaterialNames(Ogre::StringVector &names) {m_MaterialNames = names;};
		/**
		* Fetches render window handle
		* @return render window handle
		*/
		inline Ogre::RenderWindow *     GetRenderWindow() {return m_RenderWindow;};
		/**
		* Sets current render window handle
		* @param window new rendering window handle
		*/
		inline void                     SetRenderWindow(Ogre::RenderWindow *window) {m_RenderWindow = window;};
		/**
		* Fetches currently active viewport
		* @return currently active viewport
		*/
		inline CViewportEditor *        GetViewport() {return m_ActiveViewport;};
		/**
		* Sets current active viewport
		* @param viewport currently active viewport
		*/
		inline void                     SetActiveViewport(CViewportEditor *viewport) {m_ActiveViewport = viewport;};
		/**
		* Fetches current scene manager
		* @return current scene manager; if not found, returns the first Scene Manager in the list
		*/
		inline Ogre::SceneManager *     GetSceneManager()
		{
			if(!m_SceneManager)
				m_SceneManager = GetFirstSceneManager();
			return m_SceneManager;
		};
		/**
		* Fetches current scene manager editor
		* @return current scene manager editor; if not found, returns the first Scene Manager in the list
		*/
		inline CBaseEditor * GetSceneManagerEditor()
		{
			if(!m_SceneManagerEditor)
				m_SceneManagerEditor = FindObject(GetFirstSceneManager()->getName(), ETYPE_SCENEMANAGER);
			return m_SceneManagerEditor;
		};
		/**
		* Fetches a list of names for objects that are of node type
		* @param list list to place object names
		*/
		void                            GetAutoTrackTargets(Ogre::StringVector &list);
		/**
		* Fetches terrain editor
		* @return terrain editor
		*/
		inline CTerrainEditor *         GetTerrainEditor() {return m_TerrainEditor;};
		/**
		* Fetches terrain editor object (actual terrain)
		* @return terrain editor object (actual terrain)
		*/
		inline CBaseEditor *            GetTerrainEditorObject() {return m_TerrainEditorObject;};
		/**
		* Fetches first scene manager
		* @return first scene manager
		*/
		Ogre::SceneManager *            GetFirstSceneManager();
		/**
		* Tests if the scene is modified
		* @return true if scene is modified, otherwise false
		*/
		inline bool                      IsSceneModified() {return m_IsSceneModified;};
		/**
		* Tests if scene is completely loaded
		* @return true if scene is loaded, otherwise false
		*/
		inline bool                      IsSceneLoaded() {return m_IsSceneLoaded;};
		/**
		* Sets modified flag when scene has been modified
		* @param modified true if scene was modified, otherwise false
		*/
		inline void                      SetSceneModified(bool modified) {m_IsSceneModified = modified;};
		/**
		* Sets modified flag only if the value is true (Additive)
		* @param state new state
		*/
		inline void                      ChangeSceneModified(bool state) {m_IsSceneModified |= state;};
		/**
		* Hides the selection rectangle (destroys it)
		*/
		void                             HideSelectionRect();
		/**
		* Creates and shows selection rectangle
		* @param size rectangle' boundaries (x - left, y - top, z - right, w - bottom)
		*/
		void                             ShowSelectionRect(Ogre::Vector4 size);
		/**
		* Highlights gizmo(s)
		* @param ID gizmo axis(i) flag(s) to highlight 
        * @see AXISTYPE
		*/
		void                             HighlightGizmo(int ID);
		/**
		* Sets new gizmo mode 
		* @param mode new gizmo mode flag(s) 
        * @see EDITORTOOLS
		*/
		void                             SetGizmoMode(int mode);
		/**
		* Fetches light visibility
		* @return true if light(s) are visible, otherwise false
		*/
		inline bool                      GetLightVisiblity() {return m_GlobalLightVisiblity;};
		/**
		* Sets light visibility
		* @param visibility new light visibility
		*/
		void                             SetLightVisiblity(bool visibility); 
		/**
		* Fetches camera visibility state
		* @return true if camera(s) is visible, otherwise false
		*/
		inline bool                      GetCameraVisiblity() {return m_GlobalCameraVisiblity;};
		/**
		* Sets camera visibility
		* @param visibility new camera visibility
		*/
		void                             SetCameraVisiblity(bool visibility);
		/**
		* Fetches multi-selection editor handle
		* @return multi-selection editor handle
		*/
		inline CMultiSelEditor *         GetMultiSelection() {return m_MultiSelection;}
		/**
		* Recursively fills a treeview with object names and icons
		* @param pEditor an editor from which to retrieve objects
		* @param parent treeview node handle
		*/
		void RecurseFillTreeView(CBaseEditor *pEditor, void *parent);
		/**
		* Renders viewport windows after they were resized
		*/
		void                             RenderWindowResized();
		/**
		* Sets background clearing flag
		* @param bClear clearing flag
		*/
		inline void                      ClearScreenBackground(bool bClear) {m_ClearScreenBackground = bClear;};
		/**
		* Fetches background clearing flag
		* @return background clearing flag
		*/
		inline bool                      IsClearScreenNeeded() {return m_ClearScreenBackground;};
		/**
		* Fetches a list of editor preferences
		* @return list of editor preferences
		*/
		PreferenceEditorVector           GetPreferenceEditorList() {return m_PreferenceEditors;};
		/**
		* Registers new preferences for the editor
		* @param regStruct new preferences description
		*/
		void                             RegisterPreferenceEditor(PreferenceEditorRegistrationStruct &regStruct);
		/**
		* Registers a new drag&drop handler for render window
		* @param source pointer to the drag&drop source to be handled
		* @param handler pointer to the handler class for the drag&drop events originating from source
		*/
		void                             RegisterDragDropHandler(void *source, DragDropHandler *handler);
		/**
		* UnRegisters a drag&drop handler for render window
		* @param source pointer to the drag&drop source to be handled
		* @param handler pointer to the handler class for the drag&drop events originating from source
		*/
		void                             UnRegisterDragDropHandler(void *source, DragDropHandler *handler);
		/**
		* Registers QWidget-type toolbar
		* @param toolbar QWidget-type toolbar
		*/
		void                             RegisterToolBar(void *pluginIdentifier, void *toolbar);
		/**
		* Fetches a list of toolbars
		* @return list of toolbar handles
		*/
		std::vector<void*>               GetToolBars() {return m_ToolBars;};
		/**
		* Initializes recent files list with given entries
        * @param list a vector to be used as the current recent files list
		*/
		void                             InitRecentFiles(UTFStringVector& list);
		/**
		* Adds an entry to recent files list, moving it to top
        * @param entry the string to be added to the list
		*/
        void                             AddToRecentFiles(const Ogre::UTFString& entry);
		/**
		* Fetches the list of recent files, the order is: The last used is first in the list
        * @param list a vector to be flled with ordered recent files list
		*/
		void                             GetRecentFiles(UTFStringVector& list);
		/**
		* Redirects all mouse events to the registered listener class
		* @param listener class to redirect mouse events to
		*/
		inline void CaptureMouse(MouseListener *listener) { m_MouseListener = listener; };
		/**
		* Restores redirection of mouse events to the viewports
		*/
		inline void ReleaseMouse() { m_MouseListener = 0; };
		/**
		* Redirects all keyboard events to the registered listener class
		* @param listener class to redirect keyboard events to
		*/
		inline void CaptureKeyboard(KeyboardListener *listener) { m_KeyboardListener = listener; };

		/**
		* Restores redirection of keyboard events to the viewports
		*/
		inline void ReleaseKeyboard() { m_KeyboardListener = 0; };

		///EVENTS
		/**
		* Delegate function that is called when material has been dragged onto a scene (viewport)
		* @param x x mouse cursor coordinate
		* @param y y mouse cursor coordinate
		* @return true if material has been assigned to an entity, otherwise false
		*/
		bool OnDragEnter (void * source);
		/**
		* Delegate function that is called when object is being dragged around the scene (after being dragged on)
		* @param source pointer to the source of event
		* @param x x mouse cursor coordinate
		* @param y y mouse cursor coordinate
		* @return return true if the move event is accepted
		*/
		bool OnDragMove (void *source, int x, int y);
		/**
		* Delegate function that is called when dragging has concluded
		* @param source pointer to the source of event
		*/
		void OnDragLeave ();
		/**
		* Delegate function that is called when object has been dropped onto a scene
		* @param source pointer to the source of event
		* @param x x mouse cursor coordinate
		* @param y y mouse cursor coordinate
		*/
		void OnDragDropped (void *source, int x, int y);
		/** 
		* Delegate function that is called when keyboard key is held down
		* @param key code of the keyboard key that is held down
		*/
		void OnKeyDown (unsigned int key);
		/** 
		* Delegate function that is called when keyboard key has been released
		* @param key keyboard key code that has been released
		*/
		void OnKeyUp (unsigned int key);
		/** 
		* Delegate function that is called when mouse cursor is moved
		* @param point mouse cursor coordinate
		* @param buttons mouse button(s) flag
		*/
		void OnMouseMove (Ogre::Vector2 point, unsigned int buttons);
		/** 
		* Delegate function that is called when mouse cursor has left certain area
		* @param point mouse cursor coordinate
		* @param buttons mouse button(s) flag
		*/
		void OnMouseLeave (Ogre::Vector2 point, unsigned int buttons);
		/** 
		* Delegate function that is called when left mouse button is held down
		* @param point mouse cursor coordinate at the time when left mouse button had been triggered
		* @param buttons mouse button(s) flag
		*/
		void OnMouseLeftDown (Ogre::Vector2 point, unsigned int buttons);
		/** 
		* Delegate function that is called when left mouse button is released
		* @param point mouse cursor coordinate at the time when left mouse button had been triggered
		* @param buttons mouse button(s) flag
		*/
		void OnMouseLeftUp (Ogre::Vector2 point, unsigned int buttons);
		/** 
		* Delegate function that is called when right mouse button is held down
		* @param point mouse cursor coordinate at the time when right mouse button had been triggered
		* @param buttons mouse button(s) flag
		*/
		void OnMouseRightDown (Ogre::Vector2 point, unsigned int buttons);
		/** 
		* Delegate function that is called when right mouse button is released
		* @param point mouse cursor coordinate at the time when right mouse button had been triggered
		* @param buttons mouse button(s) flag
		*/
		void OnMouseRightUp (Ogre::Vector2 point, unsigned int buttons);
		/** 
		* Delegate function that is called when middle mouse button is held down
		* @param point mouse cursor coordinate at the time when middle mouse button had been triggered
		* @param buttons mouse button(s) flag
		*/
		void OnMouseMiddleDown (Ogre::Vector2 point, unsigned int buttons);
		/** 
		* Delegate function that is called when middle mouse button is released
		* @param point mouse cursor coordinate at the time when middle mouse button had been triggered
		* @param buttons mouse button(s) flag
		*/
		void OnMouseMiddleUp (Ogre::Vector2 point, unsigned int buttons);
		/** 
		* Delegate function that is called when mouse wheel is used
		* @param point mouse cursor coordinate at the time when mouse wheel is used
		* @param delta an amount of how much mouse wheel has been moved
		* @param buttons mouse button(s) flag
		*/
		void OnMouseWheel (Ogre::Vector2 point, float delta, unsigned int buttons);

	private:
		OgitorsUndoManager *m_UndoManager;								/** Undo manager handle */
		OgitorsSystem      *m_System;									/** The platform-dependent system handle */
		OgitorsPhysics     *m_Physics;									/** The platform-dependent physics handle */
		PROJECTOPTIONS      m_ProjectOptions;							/** A handle to hold all project options for the current scene */
		Ogre::SceneManager *m_SceneManager;								/** Current scene manager handle */
		CBaseEditor        *m_SceneManagerEditor;						/** Current scene manager editor handle */
		Ogre::RenderWindow *m_RenderWindow;								/** Current render window handle */
		CViewportEditor    *m_ActiveViewport;							/** The Current Viewport Pointer */
		CBaseEditor        *m_RootEditor;								/** Handle of the root editor (Actual root of all editors in a scene) */
		CBaseEditor        *m_SelectedEditor;							/** Currently selected object handle */
		CMultiSelEditor    *m_MultiSelection;							/** Multi-selection editor handle */
		NameObjectPairList  m_NameList;									/** Hash map of all objects (sorted by name) */
		NameObjectPairList  m_NamesByType[LAST_EDITOR];					/** Type-specific hash maps */
		NameObjectPairList  m_NamesByTypeID[OGITOR_MAX_OBJECT_TYPE];	/** TypeID-specific hash maps */
		NameObjectPairList  m_UpdateList;								/** Update queue */
		ObjectVector        m_PostSceneUpdateList;						/** Update list that is called after scene is loaded */
		SerializerMap       m_SerializerList;							/** Hash map of all registered serializers */
		std::vector<OgitorsRootListener*> m_RootListeners;				/** List of objects receiving root notifications */
		PluginEntryMap      m_Plugins;						            /** List of all loaded plugins */
		EditorObjectFactoryMap m_EditorObjectFactories;					/** List of all Editor Object Factories */
		Ogre::StringVector  m_MaterialNames;							/** List of material names in the current user assets directories */
		CustomPropertyList  m_CustomProperties;							/** List of currently available custom property types */
		UTFStringVector     m_RecentFiles;                              /** List of recently opened files */
        Ogre::Vector3       m_LastTranslationDelta;						/** Last object translation change (used with gizmos) */
		unsigned int        m_ObjCounter;								/** Object counter (used in assigning unique object ID) */
		CTerrainEditor     *m_TerrainEditor;							/** Terrain editor handle */
		CBaseEditor        *m_TerrainEditorObject;						/** Terrain editor object handle (actual terrain object) */
		bool                m_IsSceneModified;							/** Flag signifying if scene was modified since last save */
		bool                m_IsSceneLoaded;							/** Flag signifying if scene was successfully loaded */
		bool                m_GlobalLightVisiblity;						/** Flag determining light helper visibility */
		bool                m_GlobalCameraVisiblity;					/** Flag determining camera helper visibility */
		Ogre::Rectangle2D  *m_SelRect;									/** Selection rectangle (used for volume object selection) */
		Ogre::SceneNode    *m_SelectionNode;							/** Scene node to hold selection rectangle */
		MouseListener      *m_MouseListener;							/** Mouse listener handle (used to receive and redirect mouse events) */
		KeyboardListener   *m_KeyboardListener;							/** keyboard listener handle (used to receive and redirect keyboard events) */

		Ogre::SceneNode    *m_GizmoNode;								/** Gizmo widget handle */
		Ogre::SceneNode    *m_GizmoX;									/** X axis widget node handle */
		Ogre::SceneNode    *m_GizmoY;									/** Y axis widget node handle */
		Ogre::SceneNode    *m_GizmoZ;									/** Z axis widget node handle */
		Ogre::Entity       *m_GizmoEntites[3];							/** Gizmo handles */
		int                 m_OldGizmoMode;								/** Previous gizmo mode (@see EDITORTOOLS) */
		int                 m_OldGizmoAxis;								/** Previous gizmo axis along which transformation has occured */
		std::vector<int>    m_ObjectDisplayOrder;						/** Scene object(s) rendering order list */
		bool                m_ClearScreenBackground;					/** Flag signifying if it is time to clear screen background (used in paintEvent) */

		std::vector<void*>  m_ToolBars;									/** Additional Qt toolbars to display in Ogitor (used for tab creation) */

		PreferenceEditorVector m_PreferenceEditors;						/** Editor preferences list */
		DragDropHandlerMap     m_DragDropHandlers;						/** Drag Drop Handlers list */
        void                  *m_ActiveDragSource;                      /** Current Drag Source */

		/**
		* Cleans up editor between scene loads
		*/
		void            ClearEditors();
		/**
		* Loads binary plugin file
		* @param pluginPath the path to the plugin library file
		*/
		void            LoadPlugin(Ogre::String pluginPath);
		/**
		* Unloads all editor plugins
		*/
		void            UnLoadPlugins();
		/**
		* Notifies all listeners that scene is about to be terminated
		*/
		inline void     NotifyOnTerminateScene();
		/**
		* Notifies all listeners that scene has been loaded
		*/
		inline void     NotifyOnAfterLoadScene();
		/**
		* Notifies all listeners that scene has been updated
		*/
		inline void     NotifyOnUpdate(float time);
		/**
		* Recursively loads sub-properties of custom properties from an XML element
		* @param e XML element from which to load sub-properties from
		* @param list list which is to fill with custom properties
		*/
		void RecurseLoadCustomProperty(TiXmlElement *e,CustomPropertyList& list);
		/**
		* Test if an custom object type is in the specified list
		* @param rest list in which to search for custom object type
		* @param type type of custom object to search
		* @return true if custom object type is in the list, otherwise false
		*/
		bool IsCustomTypeRestricted(Ogre::StringVector &rest,unsigned int type);
		/**
		* Finds and registers all editor object types
		*/
		void RegisterAllEditorObjects();
		/**
		* Creates gizmo objects
		*/
		void CreateGizmo();
		/**
		* Destroys gizmo objects
		* @return
		*/
		void DestroyGizmo();
		/**
		* Updates position of gizmo objects
		* @return
		*/
		void UpdateGizmo();
		/**
		* Fills the scene tree view with objects in the scene
		*/
		void FillTreeView();
		/**
		* Registers a new editor object factory
		* @param factory pointer to new editor object factory to register
		*/
		void            _RegisterEditorFactory(CBaseEditorFactory *factory);
    };
}
